home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
asmutil
/
asm_n_z.zip
/
WHEREIS.ASM
< prev
next >
Wrap
Assembly Source File
|
1987-05-05
|
12KB
|
518 lines
name whereis
title 'WHEREIS -- find file'
page 55,132
;
; WHEREIS -- find file in directory structure
; by John Scotia, first published in Softalk/IBM
; modified by Ray Duncan
;
lf equ 0ah ;ASCII line feed
cr equ 0dh ;ASCII carriage return
ff equ 0ch ;ASCII form feed
tab equ 09h
eom equ '$' ;end of message flag
;
;Program Segment Prefix
default_fcb equ 05ch
command equ 80h
default_dta equ 080h
;
;
; This is the format for the DOS Data Transfer Area used when DOS 2.0
; searches for a file match in directories.
DTA STRUC
RESERVED DB 21 DUP (?)
ATTRIBUTE DB 0
TIME DW 0
DATE DW 0
SIZE DD 0
NAME_FOUND DB 13 DUP (?)
DTA ENDS
cseg segment para public 'CODE'
assume cs:cseg,ds:data,es:data,ss:stack
page
; This is the main program that sets up the initial conditions for
; SDIR which, in turn, does a recursive search.
;
; Reads: PATH_NAME
; Writes: FILE_NAME
; Calls: SDIR
whereis proc far
push ds ;save final return
xor ax,ax
push ax
mov bp,sp ;save pointer to final return
; in case we want to exit
; inside recursive routine
mov ax,data ;make data segment addressable
mov es,ax ;via ES
call infile ;get name of search target
mov ax,data ;make data segment addressable
mov ds,ax ;via DS
jnc whereis1 ;jump if filename was ok
;filename was missing,
mov dx,offset msg1 ;print error message and exit
mov ah,9
int 21h
ret
whereis1:
mov ah,30h ;check DOS version
int 21h
cmp al,2
jae whereis2 ;proceed, DOS 2.0 or greater
mov dx,offset msg3 ;DOS 1.1 --- print message
mov ah,9 ;and exit
int 21h
ret
whereis2:
MOV DI,OFFSET PATH_NAME
XOR AL,AL ;Search for the zero at the end
CLD ; of PATH_NAME
MOV CX,64 ;Max. length of scan for 0
REPNZ SCASB
MOV BX,DI
DEC BX ;DS:BX points to end of PATH_NAME
MOV DX,0 ;Tell SDIR this is first
CALL SDIR ;Now do the recursive search
mov ax,match_count ;were any matches found?
or ax,ax
jz whereis8 ;no,jump
ret ;yes,just exit
whereis8:
mov dx,offset msg2 ;no,print "no match"
mov ah,9
int 21h
ret
;this is a special crash
;exit, which may be taken
;from inside recursed proc.
whereis9:
mov sp,bp
ret
whereis endp
page
; This procedure searches all the files in the current directory
; looking for a match. It also prints the full name for each match.
;
; DS:BX Pointer to end of current path name
; DS:DX Old disk transfer area (DTA)
;
; Reads: Disk Transfer Area (DTA)
; Writes: Disk Transfer Area (DTA)
; Calls: BUILD_NAME, FMATCH, PNAME
; NMATCH, BUILD_STAR_NAME, SSUB
SDIR PROC NEAR
PUSH SI ;Need to restore on exit
PUSH DX
CALL BUILD_NAME ;Build the absolute search name
CALL FMATCH ;See if there is a match here
JC sdir2 ;No match, check subdirectories
CALL PNAME ;Write name of match.
sdir1:
CALL NMATCH ;Find the next match
JC sdir2 ;No match, search sub-directories
CALL PNAME ;Match, write absolute name
JMP sdir1 ;Look for the next matching name
sdir2: ;No match, so try sub-directories.
POP DX ;Restore DTA
PUSH DX
CALL BUILD_STAR_NAME ;Search for all directories
CALL FMATCH ;Get first entry
JC SDIR5 ;There are no entries
MOV SI,DX ;Put address of DTA into SI
TEST [SI].ATTRIBUTE,10H ;Is it a directory entry?
JNZ SDIR4 ;Yes, then search sub-directory
SDIR3:
CALL NMATCH ;No, then find the next match
JC SDIR5 ;There are no more entries
TEST [SI].ATTRIBUTE,10H ;Is this a directory?
JZ SDIR3 ;No, then try again
SDIR4:
CMP [SI].NAME_FOUND,'.' ;Is this a . or .. directory?
JE SDIR3 ;Yes, skip to next directory
CALL SSUB ;Search the sub-directory
PUSH AX ;Now reset the DTA
MOV AH,1AH
INT 21H
POP AX
JMP SDIR3
SDIR5:
POP DX
POP SI
RET
SDIR ENDP
page
; This procedure searches the subdirectory whos name is in the DTA
;
; DS:BX End of the current path name
; DS:[DX].NAME_FOUND Name of subdirectory for search
; Reads: PATH_NAME
; Writes: PATH_NAME
; Calls: SDIR
SSUB PROC NEAR
PUSH DI
PUSH SI
PUSH AX
PUSH BX
CLD ;Set for increment
MOV SI,DX ;Put address of DTA into SI
ADD SI,OFFSET NAME_FOUND ;Set to start of sub-directory name
MOV DI,BX ;DS:DI -- 0 at end of path name
ssub1: ;Copy sub-directory to path name
LODSB ;Copy one character
STOSB
OR AL,AL ;Was it a 0?
JNZ ssub1 ;No, keep copying
MOV BX,DI ;Set BX to end of new path name
STD ;Set flag for decrement
STOSB ;Store a 0 at end of string
MOV AL,'\'
STOSB ;Place '\' at end of path name
CALL SDIR ;Search this new path
POP BX ;Restore the old end-of-path
MOV BYTE PTR [BX],0 ;And store a zero here
POP AX
POP SI
POP DI
RET
SSUB ENDP
page
; This procedure prints the matched name after the path name
;
; DS:DX Pointer to current disk transfer area
;
; Reads: PATH_NAME, NAME_FOUND (in DTA)
; Calls: pasciiz, CRLF
PNAME PROC NEAR
PUSH AX
PUSH DX
MOV DX,OFFSET PATH_NAME
MOV AL,[BX] ;Save character at end of path
MOV BYTE PTR [BX],0 ;Set for end of string
CALL pasciiz
MOV [BX],AL ;Restore character
POP DX ;Recover old pointer
PUSH DX
ADD DX,OFFSET NAME_FOUND
CALL pasciiz
cmp byte ptr switch,'g' ;global switch set?
je pname2 ;yes,keep searching
;no, check if user wants
;to keep looking.
push dx ;save current DTA
mov dx,offset msg4 ;print 'More? '
mov ah,9
int 21h
mov ah,7 ;read console without echo
int 21h
or al,20h ;fold to lower case
cmp al,'y' ;must be y, anything else exits
je pname1
jmp whereis9 ;take crash exit
pname1: mov dl,al ;if Y,echo it
mov ah,2
int 21h
pop dx ;restore pointer to DTA
pname2: CALL CRLF
inc match_count ;count names displayed
POP DX
POP AX
RET
PNAME ENDP
page
; This procedure builds an absolute search name from PATH_NAME
; followed by FILE_NAME.
;
; Reads: FILE_NAME
; Calls: BUILD to build the name
BUILD_NAME PROC NEAR
PUSH SI
MOV SI,OFFSET FILE_NAME
CALL BUILD
POP SI
RET
BUILD_NAME ENDP
BUILD_STAR_NAME PROC NEAR
PUSH SI
MOV SI,OFFSET STAR_NAME
CALL BUILD
POP SI
RET
BUILD_STAR_NAME ENDP
; This procedure appends the string at DS:SI to PATH_NAME in
; PATH_NAME. It knows where the path name ends from knowing how
; long PATH_NAME is.
;
; DS:SI Name of file
; DS:BX End of PATH_NAME
;
; Reads: DS:SI
; Writes: PATH_NAME
BUILD PROC NEAR
PUSH AX
PUSH DI
MOV DI,BX
CLD ;Set direction for increment
build1:
LODSB ;Copy one character of name
STOSB
OR AL,AL ;End of string yet?
JNZ build1 ;No, keep copying
POP DI
POP AX
RET
BUILD ENDP
page
; This procedure finds the first match between the name given by
; DS:DX and the directory entries found in the directory PATH_NAME.
;
; DS:DX Pointer to current disk transfer area
; Returns:
; CF 0 A match was found
; 1 No match found
; AX Error code returned:
; 2 File not found
; 18 No more files
; DS:DX Pointer to new disk transfer area
;
; Reads: PATH_NAME
; Writes: dbuff
FMATCH PROC NEAR
PUSH CX
CMP DX,0 ;First one?
JA ALLOCATE ;No, then allocate space
MOV DX,OFFSET dbuff-TYPE DTA
allocate:
add dx,type dta ;no, then allocate room for new DTA
MOV CX,10H ;Search attribute for files and dirs.
MOV AH,1AH ;Set disk transfer address
INT 21H
PUSH DX ;Need DX for address of search name
MOV DX,OFFSET PATH_NAME
MOV AH,4EH ;Call for "find first match"
INT 21H
POP DX
POP CX
RET ;Return with carry flag info
FMATCH ENDP
page
; Get next match for filename
; (very similar to Get first match routine)
; Returns:
; CF 0 A match was found
; 1 No match found
; AX Error code returned:
; 2 File not found
; 18 No m